package com.five.api.configurations;


import com.five.api.security.CustomRealmWithMD5FormDB;
import com.five.api.security.ShiroFormAuthenticationFilter;
import org.apache.commons.collections.map.LinkedMap;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfiguration {
    /**
     * 声明密码匹配器
     *
     * @return
     */
    @Bean
    public static HashedCredentialsMatcher hashedCredentialsMatcher() {
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        //设置算法
        hashedCredentialsMatcher.setHashAlgorithmName("MD5");
        //散列次数
        hashedCredentialsMatcher.setHashIterations(2);
        return hashedCredentialsMatcher;
    }

    /**
     * 声明Realm（密码匹配器设置到Realm中）
     *
     * @return
     */
    @Bean
    public static CustomRealmWithMD5FormDB customRealmWithMD5FormDB(
            HashedCredentialsMatcher hashedCredentialsMatcher) {
        CustomRealmWithMD5FormDB realm = new CustomRealmWithMD5FormDB();
        realm.setCredentialsMatcher(hashedCredentialsMatcher);
        return realm;
    }



    /**
     * 声明安全管理器（Realm设置到安全管理器中）
     *
     * @return
     */
    @Bean
    public DefaultWebSecurityManager defaultWebSecurityManager(
            CustomRealmWithMD5FormDB customRealmWithMD5FormDB) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //Realm设置到安全管理器中
        securityManager.setRealm(customRealmWithMD5FormDB);
        return securityManager;
    }

    /**
     * 声明shiro 过滤器工程类
     * 修改shiro 过滤器配置
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

        //配置替换authc filter
        // 创建过滤器Map，用来装自定义过滤器
        LinkedHashMap<String, Filter> filterMap = new LinkedHashMap<>();
        // 注册过滤器对应名字
        filterMap.put("authc", new ShiroFormAuthenticationFilter());
        // 使过滤器配置生效
        shiroFilterFactoryBean.setFilters(filterMap);

        //初始化过滤器对应处理地址
        Map<String, String> filterChainDefinitionMap = initFilterChainDefinitionMap();
        //设置过滤器处理地址
        //shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);

        // 设置安全管理器
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        return shiroFilterFactoryBean;
    }

    /**
     * key 地址：value 过滤器名字
     * 配置url过滤器
     * authc：认证的过滤器
     * anon：不认证就可以访问(匿名访问) maps.put("/toIndex","anon");
     * logout：登陆过滤器 maps.put("/logout","logout")
     * perms：权限控制的
     * roles：具有某一个角色才能访问
     *
     * @return
     */
    private Map<String, String> initFilterChainDefinitionMap() {
        LinkedMap filterMap = new LinkedMap();
        //设置登录白名单
//        filterMap.put("/user/logout", "anon");
        filterMap.put("/user/login", "anon");
        filterMap.put("/user/register", "anon");
        filterMap.put("/user/code", "anon");
        filterMap.put("/article/info", "anon");
//        filterMap.put("/goods/recommendList", "anon");
        //swagger 白名单
        filterMap.put("/swagger-ui.html", "anon");
        filterMap.put("/webjars/**", "anon");
        filterMap.put("/v2/**", "anon");
        filterMap.put("/swagger-resources/**", "anon");
        //设置认证过滤器过滤地址（必须放在最后）
        filterMap.put("/**", "authc");
        return filterMap;
    }

    //    public static void main(String[] args) {
//        String hashAlgorithmName = "MD5";//加密方式
//        Object crdentials = "123456";//密码原值
//        Object salt = "abc";//盐值
//        int hashIterations = 2;//加密1024次
//        String result = new SimpleHash(hashAlgorithmName,crdentials,salt,hashIterations).toString();
//        System.out.println(result);
//    }

}
